package com.boss.salary.service.impl;

import com.boss.common.entity.WfActionDTO;
import com.boss.common.enums.ActionTypeEnum;
import com.boss.common.service.ICommonService;
import com.boss.salary.constant.SystemDictConstant;
import com.boss.salary.dao.*;
import com.boss.salary.entity.*;
import com.boss.salary.service.*;
import com.boss.salary.vo.AgencyVerifyParamVo;
import com.boss.salary.workflow.service.ISalaryWorkFlowService;
import com.boss.sys.ca.user.dto.UserDTO;
import com.boss.sys.utils.SysUtils;
import com.singularsys.jep.JepException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@EnableAsync
public class AgencySalaryAsyncServiceImpl implements IAgencySalaryAsyncService {
    /** 引入日志框架常量 */
    private final static Logger logger = LoggerFactory.getLogger(AgencySalaryServiceImpl.class);

    private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private IRedisService redisService;

    @Autowired
    private IAgencyInfoDao agencyInfoDao;



    @Autowired
    private IAgencyInfoService agencyInfoService;
    @Autowired
    private IAgencySalaryService service;
    @Autowired
    private ISalaryMonthEndService salaryMonthEndService;
    @Autowired
    private IAgencyVerifyDao agencyVerifyDao;
    @Autowired
    private ISalaryWorkFlowService iSalaryWorkFlowService;
    @Autowired
    private IAgencyVerifyService agencyVerifyService;
    @Autowired
    private IAgencySalaryService agencySalaryService;
    @Autowired
    private ICommonService iCommonService;
    @Autowired
    private IOperrateLogsService iOperrateLogsService;
    @Autowired
    private IGenerateSalaryDataService iGenerateSalaryDataService;
    @Autowired
    private ICommonService commonService;


    @Async
    @Override
    public void batchSubmitAsync(List<AgencyVerifyParamVo> agencyVerifyParamVo, UserDTO userDTO, String uuid,String tokenid) throws ParseException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, JepException {
        StringBuffer requestMessage=new StringBuffer();
        String text = "";
        DecimalFormat df=new DecimalFormat("0.00");
        logger.info("=======单位批量送审异步方法开始==============");
        try {
            for(int i=0;i<agencyVerifyParamVo.size();i++){
                batchSubmitAsyncs(agencyVerifyParamVo.get(i),userDTO,userDTO.getProvince(),requestMessage,text,tokenid);
                redisService.put(uuid,df.format((float)(i+1)/agencyVerifyParamVo.size()));
                System.out.println(df.format((float)(i+1)/agencyVerifyParamVo.size()));
                if(i+1==agencyVerifyParamVo.size()){
                    redisService.del(userDTO.getProvince()+"submitLock");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Object oj=redisService.get(userDTO.getProvince()+"submitLock");
            if(SysUtils.isNullOrEmpty(oj)){
                redisService.del(userDTO.getProvince()+"submitLock");
            }
        }
        if(StringUtils.isEmpty(requestMessage.toString())) {
            redisService.put(uuid, "S");
//            redisService.del(uuid);
        }else{
           // requestMessage.append("F");
            redisService.put(uuid,"F-"+requestMessage.toString());
//            redisService.del(uuid);
        }
        logger.info("=======单位批量送审异步方法结束==============");
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSubmitAsyncs(AgencyVerifyParamVo agencyVerifyParamVo, UserDTO userDTO, String province, StringBuffer requestMessage, String text,String tokenid) throws ParseException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, JepException {
        String hint = "";
        try{
            //添加操作日志
            OperrateLogs operrateLogs= new OperrateLogs();
            operrateLogs.setMofDivCode(userDTO.getProvince());
            operrateLogs.setTokenId(tokenid);
            operrateLogs.setUserAgencyId(userDTO.getAgency());
            operrateLogs.setUeserName(userDTO.getName());
            operrateLogs.setOperateName("单位工资编报--单位工资编报--报送财务审核");
            operrateLogs.setAgencyId(agencyVerifyParamVo.getAgencyId());
            iOperrateLogsService.saveOperrateLogs(operrateLogs);
            String type = "fileVerify";
            ConfigCtrl cc=iCommonService.selectConfigCtrlByTypeMof(type,userDTO.getProvince());
            String adjunctFlag;
            if(cc==null){
                adjunctFlag="1";
            }else{
                //1做限制0不做限制
                adjunctFlag=cc.getIsAble();
            }
//                Thread.currentThread().sleep(300);
        Map<String,Object> remap=new HashMap<>();
        boolean correct = false;
        int bankJudge = 0;
        String personNames = "";
        //根据agencyId查询PersonExt表的银行信息
        List<PersonExt> personExts = service.selectPersonExtByAgencyId(agencyVerifyParamVo.getAgencyId());
        //根据agencyId查询AgencyExt表的银行信息
        AgencyExt agencyExt = service.selectAgencyExtByAgencyId(agencyVerifyParamVo.getAgencyId());
        //根据agencyId查询单位名称
        AgencyInfo agencyInfo = agencyInfoService.getNameById(agencyVerifyParamVo.getAgencyId());
        //查询是否允许上报 subnum==0,不允许上报
        Integer subnum = service.getSubmitAble(agencyVerifyParamVo.getAgencyId());
        //查询是否有应发工资为0人员 salarynum !== 0,有应发工资为0人员
        Integer salarynum = salaryMonthEndService.getPaidWagesCount(agencyVerifyParamVo.getAgencyId(),userDTO);
        //查询是否有未经审核人员 unreviewednum !== 0,有未经审核人员
        Integer unreviewednum = salaryMonthEndService.getUnreviewedPersonCount(agencyVerifyParamVo.getAgencyId());
        //查询是否有存在未上传附件的人员 flag = true存在未上传附件的人员
        boolean flag = service.verfityExistNoFilePerson(agencyVerifyParamVo.getAgencyId());
        logger.info("====== 单位送审 Begin ===============");
        logger.info("agencyName:"+agencyInfo.getAgencyName());
        logger.info("agencyId:"+agencyVerifyParamVo.getAgencyId());
        logger.info("agencyCode:"+agencyInfo.getAgencyCode());
        if(StringUtils.isEmpty(agencyExt.getAgencyBankName())){
            bankJudge = -1;
        }else {
            for(int i=0; i<personExts.size(); i++){
                //判断是否存在银行信息不匹配人员 bankJudge = "1"，存在银行不匹配人员
                if(!agencyExt.getAgencyBankName().contains(personExts.get(i).getSalaCardBank())){
                    bankJudge += 1;
                    personNames = personNames + personExts.get(i).getPersonName()+",";
                }else {
                    bankJudge += 0;
                }
            }
        }



        if(subnum==0){
            hint="该单位不允许上报！";
        }else if(salarynum != 0){
            hint="存在工资项小于0的数据！";
        }else if(unreviewednum != 0){
            hint="有未经审核人员！";
        }else if(adjunctFlag.equals("1")&&flag){
            hint="存在未上传附件的人员！";
        }else if(bankJudge == -1){
            hint="请编辑单位信息发卡银行！";
        }else if(bankJudge > 0 ){
            hint=personNames+"银行信息不匹配！";
        }else{
            correct = true;
        }

        if(correct){
            // 执行工作流
            // 获取单位审核信息
            AgencyVerify agencyVerify = agencyVerifyDao.getInfoByAgencyId(agencyVerifyParamVo.getAgencyId());
            // 单位上报录入流程
            logger.info("==== 工资编报送审工作流 Begin ====");
            WfActionDTO<AgencyVerify> wfActionDTO = new WfActionDTO();
            wfActionDTO.setMenuguid(agencyVerifyParamVo.getMenuid());
            // 单位撤销
           if (SystemDictConstant.NO_SUBMIT.equals(String.valueOf(agencyVerify.getIsSubmitInAgency()))) {
                // 录入并送审
                wfActionDTO.setActionType(ActionTypeEnum.WF_INPUT_AUDIT.getActionTypeCode());
            }else{
                // 送审
                wfActionDTO.setActionType(ActionTypeEnum.WF_AUDIT.getActionTypeCode());
            }
            wfActionDTO.setBizDatas(agencyVerify);
            wfActionDTO.setBizKeyName("bizKey");
            iSalaryWorkFlowService.doSalaryFlow(userDTO, wfActionDTO,tokenid);
            logger.info("==== 工资编报送审工作流 End ======");
            // 修改表状态
            LocalDateTime dateTime = LocalDateTime.now();
            String updateTime = dateTime.format(DTF);
            agencyVerify.setUpdateTime(updateTime);
            agencyVerify.setIsSubmitInAgency(Integer.parseInt(SystemDictConstant.IS_SUBMIT));
            boolean ischange=false;
            try {
                ischange=agencyVerifyService.checkAgencyIsChanged(agencyVerifyParamVo.getAgencyId());
                int personNum =agencySalaryService.selectSalaryChangePersonNum(userDTO, agencyVerifyParamVo.getAgencyId(),null ,0);
                if(personNum>0){
                    ischange=true;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(ischange){
                agencyVerify.setIsSalaryChange(SystemDictConstant.IS_TRUE);
            }else{
                agencyVerify.setIsSalaryChange(SystemDictConstant.IS_FALSE);
            }
            agencyVerifyDao.updateAgencyState(agencyVerify,userDTO.getProvince());

        }
        if(!hint.equals("")){
            text+=agencyInfo.getAgencyName()+hint+"<br/>";
        }
        logger.info("agencyNote:"+hint);
        logger.info("====== 单位送审 End =================");
        requestMessage.append(text);
        }catch (Exception e){
            logger.info("批量上报后续方法错误：",e);
            requestMessage.append(text);
        }

    }





    @Async
    @Override
    public void batchAuditAsync(List<AgencyVerifyParamVo> agencyVerifyParamVo, UserDTO userDTO, String uuid,String tokenid) throws ParseException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, JepException {
        StringBuffer requestMessage=new StringBuffer();
        String text = "";
        DecimalFormat df=new DecimalFormat("0.00");
        logger.info("=======单位批量送审异步方法开始==============");
        try {
            for(int i=0;i<agencyVerifyParamVo.size();i++){
                batchAuditAsyncs(agencyVerifyParamVo.get(i),userDTO,userDTO.getProvince(),requestMessage,text,tokenid,false);
                redisService.put(uuid,df.format((float)(i+1)/agencyVerifyParamVo.size()));
                System.out.println(df.format((float)(i+1)/agencyVerifyParamVo.size()));
                if(i+1==agencyVerifyParamVo.size()){
                    redisService.del(userDTO.getProvince()+"batchLock");
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        } finally {
            Object oj=redisService.get(userDTO.getProvince()+"batchLock");
            if(SysUtils.isNullOrEmpty(oj)){
                redisService.del(userDTO.getProvince()+"batchLock");
            }
        }
        if(StringUtils.isEmpty(requestMessage.toString())) {
            redisService.put(uuid, "S");
//            redisService.del(uuid);
        }else{
            // requestMessage.append("F");
            redisService.put(uuid,"F-"+requestMessage.toString());
//            redisService.del(uuid);
        }
        logger.info("=======单位批量送审异步方法结束==============");
    }



    @Override
    public void batchAuditAsyncs(AgencyVerifyParamVo agencyVerifyParamVo, UserDTO userDTO, String province, StringBuffer requestMessage, String text,String tokenid,boolean is_one) throws ParseException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, JepException {

        String hint = "";
        boolean flag=true;
        //是否校验月份，预警月份为0时该值为false
        String months="0";
        //预警月份大与1的校验结果
        boolean monthflag=true;
        List<String> agencyids=new ArrayList<>();
        agencyids.add(agencyVerifyParamVo.getAgencyId());
        Map<String,Object> remap = new HashMap<>();
        AgencyInfo agency=agencyInfoService.getNameById(agencyVerifyParamVo.getAgencyId());
        Integer isSubmitAble = agencyInfoDao.getSubmitAble(agencyVerifyParamVo.getAgencyId());
        if(isSubmitAble==0){
            logger.info(agency.getAgencyName()+":单位不允许上报");
            hint =  "该单位不允许上报！";
        }else{
            if (!"0".equals(agency.getIsPaymentAgency())) {//判断是否是实拨单位，实拨单位冻结指标 0为实拨单位
                try {
                    remap = iGenerateSalaryDataService.isPaymentEnough(agencyids, userDTO,tokenid);//校验指标是否满足工资发放
                    flag = "true".equals(remap.get("isEnough"));
                    //是否校验月份，预警月份为0时该值为false
                    months = remap.get("months").toString();
                    //预警月份大与1的校验结果
                    monthflag = "true".equals(remap.get("isMonthsEnough"));
                } catch (Exception e) {
                    logger.info("送审异常", e);
                    hint = e.getMessage();
                    flag = false;
                }
            } else {
                flag = true;
                months = "0";
            }
            if (flag) {
                StringBuffer res = new StringBuffer();
                try {
                    if (is_one) {//是否单岗上报
                        service.submitUnitSalaryReportOne(agencyVerifyParamVo, userDTO,tokenid);//单岗上报走这个方法
                    } else {
                        service.auditUnitAudit(agencyVerifyParamVo, userDTO,tokenid);//审核通过，并上报
                    }
                } catch (Exception e) {//审核报错时解冻指标用
                    hint = e.getMessage();
                }

                if (!"0".equals(months) && !"1".equals(months) && !monthflag) {
                    res.append(agency.getAgencyName() + "审核并上报成功！但工资指标余额不够发放").append(months).append("个月");
                    commonService.pushMessageToApaas(userDTO, agencyVerifyParamVo.getAgencyId(),
                            agency.getAgencyCode() + "-" + agency.getAgencyName() + "工资指标余额不够发放" + months + "个月");
                    hint = res.toString();
                }

            } else {
                commonService.pushMessageToApaas(userDTO, agencyVerifyParamVo.getAgencyId(),
                        agency.getAgencyCode() + "-" + agency.getAgencyName() + "工资指标余额不足");
                hint = "指标余额不足！";

            }
        }
        if(!hint.equals("")){
            text+=agency.getAgencyName()+hint+"<br/>";
        }
        requestMessage.append(text);
    }






    @Async
    @Override
    public void batchAuditOneAsync(List<AgencyVerifyParamVo> agencyVerifyParamVo, UserDTO userDTO, String uuid,String tokenid) throws ParseException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, JepException {
        StringBuffer requestMessage=new StringBuffer();
        String text = "";
        DecimalFormat df=new DecimalFormat("0.00");
        logger.info("=======单位批量送审异步方法开始==============");
        try {
            for(int i=0;i<agencyVerifyParamVo.size();i++){
                batchAuditAsyncs(agencyVerifyParamVo.get(i),userDTO,userDTO.getProvince(),requestMessage,text,tokenid,true);
                redisService.put(uuid,df.format((float)(i+1)/agencyVerifyParamVo.size()));
                System.out.println(df.format((float)(i+1)/agencyVerifyParamVo.size()));
                if(i+1==agencyVerifyParamVo.size()){
                    redisService.del(userDTO.getProvince()+"submitLock");
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        } finally {
            Object oj=redisService.get(userDTO.getProvince()+"submitLock");
            if(SysUtils.isNullOrEmpty(oj)){
                redisService.del(userDTO.getProvince()+"submitLock");
            }
        }
        if(StringUtils.isEmpty(requestMessage.toString())) {
            redisService.put(uuid, "S");
//            redisService.del(uuid);
        }else{
            // requestMessage.append("F");
            redisService.put(uuid,"F-"+requestMessage.toString());
//            redisService.del(uuid);
        }
        logger.info("=======单位批量送审异步方法结束==============");
    }



    @Override
    public Map<String, String> batchSubmitUnitSalaryReport(List<AgencyVerifyParamVo> agencyVerifyParamVo, UserDTO userDTO,String tokenid) throws NoSuchMethodException, JepException, IllegalAccessException, ParseException, InvocationTargetException {
        Map<String,String> requestMap=new HashMap<>();

        String uuid="2021-"+userDTO.getProvince()+"-menuId";
        logger.info("进度:"+uuid);
        redisService.put(uuid, 0);
        requestMap.put("guid",uuid);
        if(agencyVerifyParamVo.size()>0){
            batchSubmitAsync(agencyVerifyParamVo, userDTO,uuid,tokenid);
        }

        return requestMap;
    }


    @Override
    public Map<String, String> batchAuditUnitSalaryReport(List<AgencyVerifyParamVo> agencyVerifyParamVo, UserDTO userDTO,String tokenid) throws NoSuchMethodException, JepException, IllegalAccessException, ParseException, InvocationTargetException {
        Map<String,String> requestMap=new HashMap<>();

        String uuid="2021-"+userDTO.getProvince()+"-menuId";
        logger.info("进度:"+uuid);
        redisService.put(uuid, 0);
        requestMap.put("guid",uuid);
        if(agencyVerifyParamVo.size()>0){
            batchAuditAsync(agencyVerifyParamVo, userDTO,uuid,tokenid);
        }

        return requestMap;
    }


    @Override
    public Map<String, String> batchAuditUnitSalaryReportOne(List<AgencyVerifyParamVo> agencyVerifyParamVo, UserDTO userDTO,String tokenid) throws NoSuchMethodException, JepException, IllegalAccessException, ParseException, InvocationTargetException {
        Map<String,String> requestMap=new HashMap<>();

        String uuid="2021-"+userDTO.getProvince()+"-menuId";
        logger.info("进度:"+uuid);
        redisService.put(uuid, 0);
        requestMap.put("guid",uuid);
        if(agencyVerifyParamVo.size()>0){
            batchAuditOneAsync(agencyVerifyParamVo, userDTO,uuid,tokenid);
        }

        return requestMap;
    }





}
